<?php

namespace App\Jobs;

use App\Models\TiebaCrawlerStatus;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use QL\QueryList;
use App\Models\Chapter;
use App\Models\Repository;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;

class TiebaJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /** @var integer 数据库贴吧抓取状态的主键ID */
    private $id;

    /**
     * Create a new job instance.
     *
     * @param $id
     */
    public function __construct($id)
    {

        $this->id = $id;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        Model::unsetEventDispatcher();

        $url = function ($id, $page = 1) {

            return 'https://tieba.baidu.com/p/'.$id.'?see_lz=1&pn='.$page;
        };
        $get = function ($id, $page = 1) use ($url): QueryList {
            Log::info($url($id, $page));

            return QueryList::get($url($id, $page));
        };
        $parse = function (QueryList $ql) {
            $max_page = $ql->find('[max-page]')->attrs('max-page')[0] ?? 1;
            $title = $ql->find('.core_title_txt')->texts()[0];

            return compact('max_page', 'title');
        };
        $parse_data = function (QueryList $ql) use ($get) {
            $rules = [
                'field' => [
                    '.d_post_content',
                    'text',
                ],
                'json' => [
                    '',
                    'data-field',
                    null,
                    function ($json) {
                        return json_decode($json, true);
                    },
                ],
                'created_at' => [
                    '.tail-info:last-child',
                    'text',
                    null,
                    function ($time) {
                        return $time.':00';
                    },
                ],
            ];
            $rt = $ql->rules($rules)->range('.p_postlist .l_post')->query()->getData()->toArray();

            return $rt;
        };
        $status = TiebaCrawlerStatus::find($this->id);
        $status->status = $status::STATUS_PREPARING;
        $status->save();
        $html = $get($status->post_id);

        $info = $parse($html);
        $status->status = $status::STATUS_FETCHING;
        $status->current_page = 1;
        $status->total_page = $info['max_page'];
        $status->save();
        $posts = $parse_data($html);

        //$info['name'] = $posts[0]['json']['author']['user_name'];

        for ($page = 2; $page <= $info['max_page']; $page++) {
            $status->current_page = $page;
            $status->save();
            $html = $get($status->post_id, $page);
            $posts = array_merge($posts, $parse_data($html));
        }

        $data = $info + ['posts' => $posts];
        $status->status = $status::STATUS_FETCHED;
        $status->save();
        $author = $status->user;
        $repository = $author->repositories()->create([
            'title' => $data['title'],
            'url' => 'https://tieba.baidu.com/p/'.$status->post_id,
            'type' => 0,
        ]);

        foreach ($data['posts'] as $index => $post) {
            if ($post['created_at']) {
                $time = $post['created_at'];
            } elseif (Arr::has($post, 'json.content.date')) {
                $time = $post['json.content.date'].':00';
            } else {
                $time = now();
            }
            $repository->chapters()->save(new Chapter([
                'content' => $post['field'],
                'user_id' => $author->id,
                'created_at' => $time,
                'updated_at' => $time,
            ]), ['is_using' => 1, 'sequence' => $index + 1]);
        }
        $status->status = $status::STATUS_DONE;
        $status->repository_id = $repository->id;
        $status->save();
    }
}
